package com.android.nodejs.livejs.activities;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Calendar;

import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.android.nodejs.livejs.R;
import com.android.nodejs.livejs.constants.AddMessageConstants;
import com.android.nodejs.livejs.constants.ConnectionConstants;
import com.android.nodejs.livejs.constants.DisplayConstants;
import com.android.nodejs.livejs.utils.CommonUtil;

@SuppressLint("HandlerLeak")
public class SignUpActivity extends Activity {

    private EditText edtFullName;
    private EditText edtEmail;
    private EditText edtPassword;
    private EditText edtConfirmPassword;
    private EditText edtBirthDay;
    private RadioGroup rgGender;
    private RadioButton rbMale;
    private RadioButton rbFemale;
    private ImageView btnSignUp;
    private ImageView btnResetText;
    private ImageView btnCancel;

    private int pYear;
    private int pMonth;
    private int pDay;

    private Socket socket = null;
    private InputStream is = null;
    private OutputStream os = null;

    private ProgressDialog progressDialog;
    private String strServerResponse = "";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sign_up);

        /* Get the current date */
        final Calendar cal = Calendar.getInstance();
        pYear = cal.get(Calendar.YEAR);
        pMonth = cal.get(Calendar.MONTH);
        pDay = cal.get(Calendar.DAY_OF_MONTH);

        edtFullName = (EditText) findViewById(R.id.edtFullName);
        edtEmail = (EditText) findViewById(R.id.edtEmail);
        edtPassword = (EditText) findViewById(R.id.edtPassword);
        edtConfirmPassword = (EditText) findViewById(R.id.edtConfirmPassword);
        edtBirthDay = (EditText) findViewById(R.id.edtBirthDay);
        rgGender = (RadioGroup) findViewById(R.id.rgGender);
        rbMale = (RadioButton) findViewById(R.id.rbMale);
        rbFemale = (RadioButton) findViewById(R.id.rbFemale);
        btnSignUp = (ImageView) findViewById(R.id.btnSignUp);
        btnSignUp.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (isNullAllFields()) { // null all fields
                    Toast.makeText(getApplicationContext(), "Please fill all fields!", Toast.LENGTH_LONG).show();
                } else if (!checkValidateEmail(edtEmail.getText().toString())) {
                    Toast.makeText(getApplicationContext(), "Wrong email address format!", Toast.LENGTH_LONG).show();
                } else if (!checkConfirmPassword(edtPassword.getText().toString(), edtConfirmPassword.getText().toString())) {
                    Toast.makeText(getApplicationContext(), "Confirmpassword do not match!", Toast.LENGTH_LONG).show();
                } else {// process sign up
                    progressDialog = ProgressDialog.show(SignUpActivity.this, "", "Signing up...");
                    new Thread(new Runnable() {
                        public void run() {
                            try {
                                SocketAddress sockAddr = new InetSocketAddress(ConnectionConstants.IP, ConnectionConstants.PORT);
                                socket = new Socket();
                                int timeoutMs = 20000;
                                socket.connect(sockAddr, timeoutMs);
                                is = socket.getInputStream();
                                os = socket.getOutputStream();
                                if (os == null) {
                                    if (progressDialog.isShowing()) {
                                        progressDialog.dismiss();
                                    }
                                    return;
                                }
                                BufferedWriter w = new BufferedWriter(new OutputStreamWriter(os));
                                w.write(AddMessageConstants.SIGN_UP);
                                JSONObject jsonUser = new JSONObject();
                                jsonUser.put("full_name", edtFullName.getText().toString().trim());
                                jsonUser.put("email", edtEmail.getText().toString().trim());
                                jsonUser.put("password", CommonUtil.convertToMD5(edtPassword.getText().toString().trim()));
                                jsonUser.put("birthday", edtBirthDay.getText().toString().trim());
                                jsonUser.put("gender", rbMale.isChecked() ? 1 : 0);
                                w.write(jsonUser.toString());
                                w.flush();

                                MessageHanlder messageHanlder = new MessageHanlder();
                                messageHanlder.start();
                                
                                if (progressDialog.isShowing()) {
                                    progressDialog.dismiss();
                                }
                            } catch (SocketTimeoutException e) {
                                if (progressDialog.isShowing()) {
                                    progressDialog.dismiss();
                                }
                                Message msg = toastHandler.obtainMessage(3);
                                toastHandler.sendMessage(msg);
                                return;
                            } catch (UnknownHostException e) {
                                Log.d("UnknownHostException", e.getClass().getSimpleName() + ": " + e.getMessage());
                                e.printStackTrace();
                            } catch (IOException e) {
                                Log.d("IOException", e.getClass().getSimpleName() + ": " + e.getMessage());
                                e.printStackTrace();
                            } catch (JSONException e) {
                                Log.d("JSONException", e.getClass().getSimpleName() + ": " + e.getMessage());
                                e.printStackTrace();
                            } catch (Exception e) {
                                Log.d("Exception", e.getClass().getSimpleName() + ": " + e.getMessage());
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
            }
        });
        btnResetText = (ImageView) findViewById(R.id.btnResetText);
        btnResetText.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                edtFullName.setText(null);
                edtEmail.setText(null);
                edtPassword.setText(null);
                edtConfirmPassword.setText(null);
                edtBirthDay.setText(null);
                rgGender.clearCheck();
            }
        });
        btnCancel = (ImageView) findViewById(R.id.btnCancel);
        btnCancel.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "Cancel button is press!", Toast.LENGTH_LONG).show();
            }
        });
    }

    public void onClickSignIn(View v) {
        onBackPressed();
    }

    DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            switch (which) {
                case DialogInterface.BUTTON_POSITIVE:
                    // Yes button clicked
                    setResult(RESULT_CANCELED);
                    finish();
                    break;
                case DialogInterface.BUTTON_NEGATIVE:
                    // No button clicked
                    break;
            }
        }
    };

    @Override
    public void onBackPressed() {
        // check not null all fields
        if (!"".equals(edtFullName.getText().toString().trim()) || !"".equals(edtEmail.getText().toString().trim())
                || !"".equals(edtPassword.getText().toString().trim()) || !"".equals(edtConfirmPassword.getText().toString().trim())
                || !"".equals(edtBirthDay.getText().toString().trim()) || (rbMale.isChecked() || rbFemale.isChecked())) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Are you sure want to cancel the register?").setPositiveButton("Yes", dialogClickListener)
                    .setNegativeButton("No", dialogClickListener).show();
        } else {
            setResult(RESULT_CANCELED);
            finish();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_sign_up, menu);
        return true;
    }

    /**
     * onClick for choose BirthDay button
     * 
     * @param v
     */
    @SuppressWarnings("deprecation")
    public void onClickDatePicker(View v) {
        showDialog(0);
    }

    /**
     * check null all fields
     * 
     * @return true if have a field is null, invert return false if haven't
     */
    public boolean isNullAllFields() {
        if ("".equals(edtFullName.getText().toString().trim()) || "".equals(edtEmail.getText().toString().trim())
                || "".equals(edtPassword.getText().toString().trim()) || "".equals(edtConfirmPassword.getText().toString().trim())
                || "".equals(edtBirthDay.getText().toString().trim()) || (!rbMale.isChecked() && !rbFemale.isChecked())) {
            return true;
        }
        return false;
    }

    /**
     * check validate email address format
     * 
     * @param email_address
     * @return true if valid, false if invalid
     */
    public boolean checkValidateEmail(String email_address) {
        return email_address.matches("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$");
    }

    /**
     * check the same password with confirm password
     * 
     * @param pass
     * @param confirmPass
     * @return true if equals, false if not same
     */
    public boolean checkConfirmPassword(String pass, String confirmPass) {
        return pass.equals(confirmPass);
    }

    // =======date picker============
    /** Callback received when the user "picks" a date in the dialog */
    private DatePickerDialog.OnDateSetListener pDateSetListener = new DatePickerDialog.OnDateSetListener() {
        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
            pYear = year;
            pMonth = monthOfYear;
            pDay = dayOfMonth;
            updateDisplay();
        }
    };

    /** Updates the date in the TextView */
    private void updateDisplay() {
        edtBirthDay.setText(new StringBuilder()
        // Month is 0 based so add 1
                .append(pYear).append("/").append(pMonth + 1).append("/").append(pDay));
    }

    /** Create a new dialog for date picker */
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case 0:
                return new DatePickerDialog(this, pDateSetListener, pYear, pMonth, pDay);
        }
        return null;
    }

    /** Show Toast message */
    private Handler toastHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0) {
                Toast.makeText(getApplicationContext(), DisplayConstants.DIS_EXISTED_ACCOUNT, Toast.LENGTH_LONG).show();
            } else if (msg.what == 1) {
                Toast.makeText(getApplicationContext(), DisplayConstants.DIS_SIGNED_UP, Toast.LENGTH_LONG).show();
            } else if (msg.what == 2) {
                Toast.makeText(getApplicationContext(), DisplayConstants.DIS_SIGN_UP_FAIL, Toast.LENGTH_LONG).show();
            } else if (msg.what == 3) {
                CommonUtil.dialogNotify(SignUpActivity.this, DisplayConstants.DIS_CONNECT_SERVER_FAIL);
            }
        }
    };

    /**
     * get message from server response
     * 
     * @author vuvt
     * 
     */
	private class MessageHanlder extends Thread {
		@Override
        public void run() {
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            try {
                StringBuffer b = new StringBuffer();
                String t = r.readLine();
                b.append(t);
                strServerResponse = b.toString().trim();
                b.delete(0, b.length());
                if (ConnectionConstants.RES_EXISTED_ACCOUNT.equals(strServerResponse)) {
                    // = 0: show toast with message account is not exist
                    Message msg = toastHandler.obtainMessage(0);
                    toastHandler.sendMessage(msg);
                } else if (ConnectionConstants.RES_SIGNED_UP.equals(strServerResponse)) {
                    // = 1: show toast with message sign up success
                    Message msg = toastHandler.obtainMessage(1);
                    toastHandler.sendMessage(msg);
                    // finish SignUpActivity
                    finish();
                } else if (ConnectionConstants.RES_SIGN_UP_FAIL.equals(strServerResponse)) {
                    // = 2: show toast with message sign up fail
                    Message msg = toastHandler.obtainMessage(2);
                    toastHandler.sendMessage(msg);
                }
            } catch (IOException e) {
                Log.d("VuVT-IOException", e.getClass().getSimpleName() + ": " + e.getMessage());
            }
            super.run();
        }
    }
}
